//
// Created by martin on 2/16/22.
//

#include "muduo/net/Buffer.h"
#include "muduo/net/SocketsOps.h"

#include <errno.h>
#include <sys/uio.h> // readv

using namespace muduo;
using namespace muduo::net;

const char Buffer::kCRLF[] = "\r\n";

const size_t Buffer::kCheapPrepend;
const size_t Buffer::kInitialSize;

/**
 * 从fd读取数据到内部缓冲区, 将系统调用错误保存至savedErrno
 * @param 要读取的fd, 通常是代表连接的conn fd
 * @param savedErrno[out] 保存的错误号
 * @return 读取数据结果. < 0, 发生错误; >= 成功, 读取到的字节数
 */
ssize_t Buffer::readFd(int fd, int* savedErrno)
{
    // saved an ioctl()/FIONREAD call to tell how much to read.
    char extrabuf[65536]; // 65536 = 64K bytes
    struct iovec vec[2];
    const size_t writable = writableBytes();
    vec[0].iov_base = begin() + writerIndex_;
    vec[0].iov_len = writable;
    vec[1].iov_base = extrabuf;
    vec[1].iov_len = sizeof(extrabuf);

    const int iovcnt = (writable < sizeof(extrabuf)) ? 2 : 1;
    const ssize_t n = sockets::readv(fd, vec, iovcnt);
    if (n < 0)
    { // ::readv系统调用错误
        *savedErrno = errno;
    }
    else if (implicit_cast<size_t>(n) <= writable)
    {
        writerIndex_ += n;
    }
    else
    {// 读取的数据超过现有内部buffer_的writable空间大小时, 启用备用的extrabuf 64KB空间, 并将这些数据添加到内部buffer_的末尾
        // 过程可能会合并多余prependable空间或resize buffer_大小, 以腾出足够writable空间存放数据
        // n >= 0 and n > writable
        // => buffer_ is full, then append extrabuf to buffer_
        writerIndex_ = buffer_.size();
        append(extrabuf, n - writable);
    }
    return n;
}
